-module(tests).

-include_lib("eunit/include/eunit.hrl").
-compile(export_all).

application_start_test_() ->
    [ ?_assertMatch({ok, _},
                    application:ensure_all_started(stringprep)),
      ?_assertEqual(ok, stringprep:start()) ].

application_start_stop_start_test_() ->
    [ ?_assertEqual({ok, []},
                    application:ensure_all_started(stringprep)),
      ?_assertEqual(ok, application:stop(stringprep)),
      ?_assertEqual(ok, stringprep:start()) ].

badarg_test() ->
    ?assertError(badarg, stringprep:nodeprep(foo)),
    ?assertError(badarg, stringprep:nameprep(123)),
    ?assertError(badarg, stringprep:resourceprep({foo, bar})),
    ?assertError(badarg, stringprep:tolower(fun() -> ok end)).

empty_string_test() ->
    ?assertEqual(<<>>, stringprep:nodeprep(<<>>)),
    ?assertEqual(<<>>, stringprep:nameprep(<<>>)),
    ?assertEqual(<<>>, stringprep:resourceprep(<<>>)),
    ?assertEqual(<<>>, stringprep:tolower(<<>>)).

'@_nodeprep_test'() ->
    ?assertEqual(error, stringprep:nodeprep(<<"@">>)).

tolower_test() ->
    ?assertEqual(<<"abcd">>, stringprep:tolower(<<"AbCd">>)).

resourceprep_test() ->
    ?assertEqual(
       <<95,194,183,194,176,226,137,136,88,46,209,130,208,189,206,
         181,32,208,188,97,206,183,32,195,143,197,139,32,196,174,
         209,143,207,131,206,174,32,208,188,97,115,208,186,46,88,
         226,137,136,194,176,194,183,95>>,
       stringprep:resourceprep(
         <<95,194,183,194,176,226,137,136,88,46,209,130,208,189,
           206,181,32,208,188,194,170,206,183,32,195,143,197,139,
           32,196,174,209,143,207,131,206,174,32,208,188,194,170,
           115,208,186,46,88,226,137,136,194,176,194,183,95>>)).

nameprep_fail_test() ->
    ?assertEqual(error,
                 stringprep:nameprep(<<217,173,65,112,107,97,119,97,217,173>>)).

vector_test() ->
    Cases = [
             {<<"foo", 16#C2, 16#AD, 16#CD, 16#8F, 16#E1, 16#A0, 16#86, 16#E1, 16#A0, 16#8B,
                "bar", 16#E2, 16#80, 16#8B, 16#E2, 16#81, 16#A0, "baz", 16#EF, 16#B8, 16#80,
                16#EF, 16#B8, 16#88, 16#EF, 16#B8, 16#8F, 16#EF, 16#BB, 16#BF>>,
              <<"foobarbaz">>,
              <<"foobarbaz">>,
              <<"foobarbaz">>,
              <<"foobarbaz">>},
             {<<"CAFE">>,
              <<"cafe">>,
              <<"cafe">>,
              <<"CAFE">>,
              <<"cafe">>},
             {<<16#C3, 16#9F>>,
              <<"ss">>,
              <<"ss">>,
              <<16#C3, 16#9F>>,
              <<"ss">>},
             {<<16#C4, 16#B0>>,
              <<"i", 16#CC, 16#87>>,
              <<"i", 16#CC, 16#87>>,
              <<16#C4, 16#B0>>,
              <<"i", 16#CC, 16#87>>},
             {<<16#C5, 16#83, 16#CD, 16#BA>>,
              <<16#C5, 16#84, " ", 16#CE, 16#B9>>,
              error,
              <<16#C5, 16#83, " ", 16#CD, 16#85>>,
              <<16#C5, 16#84, " ", 16#CE, 16#B9>>},
             {<<16#E2, 16#84, 16#A1, 16#E3, 16#8F, 16#86, 16#F0, 16#9D, 16#9E, 16#BB>>,
              <<"telC", 16#E2, 16#88, 16#95, "kg", 16#CF, 16#83>>,
              <<"telC", 16#E2, 16#88, 16#95, "kg", 16#CF, 16#83>>,
              <<"TELC", 16#E2, 16#88, 16#95, "kg", 16#CF, 16#82>>,
              <<"telC", 16#E2, 16#88, 16#95, "kg", 16#CF, 16#83>>},
             {<<"j", 16#CC, 16#8C, 16#C2, 16#A0, 16#C2, 16#AA>>,
              <<16#C7, 16#B0, " a">>,
              error,
              <<16#C7, 16#B0, " a">>,
              <<16#C7, 16#B0, " a">>},
             {<<16#E1, 16#BE, 16#B7>>,
              <<16#E1, 16#BE, 16#B6, 16#CE, 16#B9>>,
              <<16#E1, 16#BE, 16#B6, 16#CE, 16#B9>>,
              <<16#E1, 16#BE, 16#B7>>,
              <<16#E1, 16#BE, 16#B6, 16#CE, 16#B9>>},
             {<<16#C7, 16#F0>>,
              error,
              error,
              error,
              error},
             {<<16#CE, 16#90>>,
              <<16#CE, 16#90>>,
              <<16#CE, 16#90>>,
              <<16#CE, 16#90>>,
              <<16#CE, 16#90>>},
             {<<16#CE, 16#B0>>,
              <<16#CE, 16#B0>>,
              <<16#CE, 16#B0>>,
              <<16#CE, 16#B0>>,
              <<16#CE, 16#B0>>},
             {<<16#E1, 16#BA, 16#96>>,
              <<16#E1, 16#BA, 16#96>>,
              <<16#E1, 16#BA, 16#96>>,
              <<16#E1, 16#BA, 16#96>>,
              <<16#E1, 16#BA, 16#96>>},
             {<<16#E1, 16#BD, 16#96>>,
              <<16#E1, 16#BD, 16#96>>,
              <<16#E1, 16#BD, 16#96>>,
              <<16#E1, 16#BD, 16#96>>,
              <<16#E1, 16#BD, 16#96>>},
             {<<" ">>,
              <<" ">>,
              error,
              <<" ">>,
              <<" ">>},
             {<<16#C2, 16#A0>>,
              <<" ">>,
              error,
              <<" ">>,
              <<" ">>},
             {<<16#E1, 16#9A, 16#80>>,
              error,
              error,
              error,
              error},
             {<<16#E2, 16#80, 16#80>>,
              <<" ">>,
              error,
              <<" ">>,
              <<" ">>},
             {<<16#E2, 16#80, 16#8B>>,
              <<>>,
              <<>>,
              <<>>,
              <<>>},
             {<<16#E3, 16#80, 16#80>>,
              <<" ">>,
              error,
              <<" ">>,
              <<" ">>},
             {<<16#10, 16#7f>>,
              <<16#10, 16#7f>>,
              error,
              error,
              <<16#10, 16#7f>>},
             {<<16#C2, 16#85>>,
              error,
              error,
              error,
              error},
             {<<16#E1, 16#A0, 16#8E>>,
              error,
              error,
              error,
              error},
             {<<16#EF, 16#BB, 16#BF>>,
              <<>>,
              <<>>,
              <<>>,
              <<>>},
             {<<16#F0, 16#9D, 16#85, 16#B5>>,
              error,
              error,
              error,
              error},
             {<<16#EF, 16#84, 16#A3>>,
              error,
              error,
              error,
              error},
             {<<16#F3, 16#B1, 16#88, 16#B4>>,
              error,
              error,
              error,
              error},
             {<<16#F4, 16#8F, 16#88, 16#B4>>,
              error,
              error,
              error,
              error},
             {<<16#F2, 16#8F, 16#BF, 16#BE>>,
              error,
              error,
              error,
              error},
             {<<16#F4, 16#8F, 16#BF, 16#BF>>,
              error,
              error,
              error,
              error},
             {<<16#ED, 16#BD, 16#82>>,
              error,
              error,
              error,
              error},
             {<<16#EF, 16#BF, 16#BD>>,
              error,
              error,
              error,
              error},
             {<<16#E2, 16#BF, 16#B5>>,
              error,
              error,
              error,
              error},
             {<<16#CD, 16#81>>,
              <<16#CC, 16#81>>,
              <<16#CC, 16#81>>,
              <<16#CC, 16#81>>,
              <<16#CC, 16#81>>},
             {<<16#E2, 16#80, 16#8E>>,
              error,
              error,
              error,
              error},
             {<<16#E2, 16#80, 16#AA>>,
              error,
              error,
              error,
              error},
             {<<16#F3, 16#A0, 16#80, 16#81>>,
              error,
              error,
              error,
              error},
             {<<16#F3, 16#A0, 16#81, 16#82>>,
              error,
              error,
              error,
              error},
             {<<"foo", 16#D6, 16#BE, "bar">>,
              error,
              error,
              error,
              error},
             {<<"foo", 16#EF, 16#B5, 16#90, "bar">>,
              error,
              error,
              error,
              error},
             {<<"foo", 16#EF, 16#B9, 16#B6, "bar">>,
              <<"foo ", 16#D9, 16#8E, "bar">>,
              error,
              <<"foo ", 16#D9, 16#8E, "bar">>,
              <<"foo ", 16#D9, 16#8E, "bar">>},
             {<<16#D8, 16#A7, "1">>,
              error,
              error,
              error,
              error},
             {<<16#D8, 16#A7, "1", 16#D8, 16#A8>>,
              <<16#D8, 16#A7, "1", 16#D8, 16#A8>>,
              <<16#D8, 16#A7, "1", 16#D8, 16#A8>>,
              <<16#D8, 16#A7, "1", 16#D8, 16#A8>>,
              <<16#D8, 16#A7, "1", 16#D8, 16#A8>>},
             {<<16#F3, 16#A0, 16#80, 16#82>>,
              error,
              error,
              error,
              error},
             {<<"X", 16#C2, 16#AD, 16#C3, 16#9F, 16#C4, 16#B0, 16#E2, 16#84, 16#A1, "j", 16#CC, 16#8C,
                16#C2, 16#A0, 16#C2, 16#AA, 16#CE, 16#B0, 16#E2, 16#80, 16#80>>,
              <<"xssi", 16#CC, 16#87, "tel", 16#C7, 16#B0, " a", 16#CE, 16#B0, " ">>,
              error,
              <<"X", 16#C3, 16#9F, 16#C4, 16#B0, "TEL", 16#C7, 16#B0, " a", 16#CE, 16#B0, " ">>,
              <<"xssi", 16#CC, 16#87, "tel", 16#C7, 16#B0, " a", 16#CE, 16#B0, " ">>},
             {<<"X", 16#C3, 16#9F, 16#E3, 16#8C, 16#96, 16#C4, 16#B0, 16#E2, 16#84, 16#A1, 16#E2, 16#92,
                16#9F, 16#E3, 16#8C, 16#80>>,
              <<"xss", 16#E3, 16#82, 16#AD, 16#E3, 16#83, 16#AD, 16#E3, 16#83, 16#A1, 16#E3, 16#83, 16#BC,
                16#E3, 16#83, 16#88, 16#E3, 16#83, 16#AB, "i", 16#CC, 16#87, "tel(d)", 16#E3, 16#82, 16#A2,
                16#E3, 16#83, 16#91, 16#E3, 16#83, 16#BC, 16#E3, 16#83, 16#88>>,
              <<"xss", 16#E3, 16#82, 16#AD, 16#E3, 16#83, 16#AD, 16#E3, 16#83, 16#A1, 16#E3, 16#83, 16#BC,
                16#E3, 16#83, 16#88, 16#E3, 16#83, 16#AB, "i", 16#CC, 16#87, "tel(d)", 16#E3, 16#82, 16#A2,
                16#E3, 16#83, 16#91, 16#E3, 16#83, 16#BC, 16#E3, 16#83, 16#88>>,
              <<"X", 16#C3, 16#9F, 16#E3, 16#82, 16#AD, 16#E3, 16#83, 16#AD, 16#E3, 16#83, 16#A1, 16#E3,
                16#83, 16#BC, 16#E3, 16#83, 16#88, 16#E3, 16#83, 16#AB, 16#C4, 16#B0, "TEL(d)", 16#E3, 16#82,
                16#A2, 16#E3, 16#83, 16#91, 16#E3, 16#83, 16#BC, 16#E3, 16#83, 16#88>>,
              <<"xss", 16#E3, 16#82, 16#AD, 16#E3, 16#83, 16#AD, 16#E3, 16#83, 16#A1, 16#E3, 16#83, 16#BC,
                16#E3, 16#83, 16#88, 16#E3, 16#83, 16#AB, "i", 16#CC, 16#87, "tel(d)", 16#E3, 16#82, 16#A2,
                16#E3, 16#83, 16#91, 16#E3, 16#83, 16#BC, 16#E3, 16#83, 16#88>>}
            ],
    lists:foreach(fun({Arg, Name, Node, Resource, Lower}) ->
                          ?assertEqual(Name, stringprep:nameprep(Arg)),
                          ?assertEqual(Node, stringprep:nodeprep(Arg)),
                          ?assertEqual(Resource, stringprep:resourceprep(Arg)),
                          ?assertEqual(Lower, stringprep:tolower(Arg))
                  end, Cases).

application_stop_test() ->
    ?assertEqual(ok, application:stop(stringprep)).
